1、 并发和竞争
	在以下情况会存在并发：
		1）进程与进程之间，一个进程会被另一个进程打断，或进程时间片结束自动放弃CPU，
	或多个CPU核心同时运行多个进程
		2）进程和软中断之间，本核心的进程可能会被本核心的软中断打断
		3）进程和硬中断之间，本核心的进程可能会被本核心的硬中断打断
		4）软中断和硬中断之间，本核心的软中断可能会被本核心的硬中断打断
		5）多个 CPU 核心之间，多个 CPU 核心除了会同时运行多个进程外，可能还会同时运行
	多个软中断或硬中断
	在并发状态对共享资源进行访问将出现竞争。
2、 竞争解决办法
	1）进程与进程之间
		可使用信号量、互斥量、自旋锁解决竞争问题（当临界区执行时间较长不推介自旋锁）。
	2）进程和软中断之间
		采用关闭软中断，并结合自旋锁解决竞争问题，在进程中关闭软中断（防止本核软中断
	抢占），然后获取自旋锁（防止其他 CPU 核心抢占），在软中断中获取自旋锁（防止其他 
	CPU核心抢占）。
	3）进程和硬中断之间
		与进程和软中断之间类似，只是这里要关闭的是硬中断。
	4）软中断和硬中断之间
		采用自旋锁，并结合关闭硬中断解决，在软中断中关闭硬中断（防止本核硬中断抢占），
	然后获取自旋锁（防止其他 CPU 核心抢占），在硬中断中获取自旋锁（防止其他	CPU核心抢
	占）。
	5）软中断与软中断之间，或硬中断与硬中断之间
		此情况只存在与多核系统中，对于这种情况下的竞争问题通过自旋锁即可解决（Linux不
	支持中断嵌套，即本核的软中断不能打断本核的软中断，本核的硬中断也不能打断本核的硬中
	断，所以解决软中断与软中断之间竞争不必关闭软中断，解决硬中断与硬中断之间竞争不必关
	闭硬中断）。
3、 自旋锁
	自旋锁API：
		//定义并初始化一个自选变量。
		DEFINE_SPINLOCK(spinlock_t lock)
		//初始化自旋锁
		void spin_lock_init(spinlock_t *lock)
		//获取自旋锁，也叫做加锁。
		void spin_lock(spinlock_t *lock)
		//尝试获自旋锁，如果没有获取到就返回 0
		int spin_trylock(spinlock_t *lock)
		//检查自旋锁是否被获取，如果没有被获取就返回非 0，否则返回 0
		int spin_is_locked(spinlock_t *lock)
		//释放自旋锁。
		void spin_unlock(spinlock_t *lock)
		//关闭软中断，并获取自动锁
		void spin_lock_bh(spinlock_t *lock)
		//开启软中断，并释放自旋锁
		void spin_unlock_bh(spinlock_t *lock)
		//关闭中断，并获取自动锁
		void spin_lock_irq(spinlock_t *lock)
		//开启中断，并释放自旋锁
		void spin_unlock_irq(spinlock_t *lock)
		//关闭中断，然后保存中断状态，并获取自旋锁
		void spin_lock_irqsave(spinlock_t *lock, unsigned long flags)
		//恢复中断状态，并释放自旋锁
		void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
	自旋锁特性：
		1）在获取自旋锁的过程中不会引起进程休眠，所以自旋锁可以在中断中使用，而且加锁
	的时间要尽可能的短、在加锁过程中不可执行可能会引起进程休眠的函数。
		2）自旋锁不可递归使用，加锁和解锁必须成对使用
		3）在使用自旋锁解决进程和中断间的竞争时，在进程中必须采用 spin_lock_irqsave 和
	spin_unlock_irqrestore 来进行加锁和解锁（防止进程获取到自旋锁后被中断打断，从而导
	致死锁）
5、 信号量
	信号量API：
		//定义一个信号量，并且设置信号量的值为 1
		DEFINE_SEMAPHORE(name)
		//初始化信号量 sem，设置信号量值为 val。
		void sema_init(struct semaphore *sem, int val)
		//获取信号量
		void down(struct semaphore *sem)
		//尝试获取信号量，不会进入休眠，可以在中断中使用
		int down_trylock(struct semaphore *sem);
		//获取信号量，但是休眠后能被信号唤醒
		int down_interruptible(struct semaphore *sem)
		//获取信号量，但是休眠后能被SIGKILL唤醒
		int down_killable(struct semaphore *sem)
		//在指定时间内获取信号量
		int down_timeout(struct semaphore *sem, long jiffies)
		//释放信号量
		void up(struct semaphore *sem)
	信号量的特性：
		1）获取信号量时如果信号量不可用，在除 down_trylock 外都会让进程休眠进行休眠，
	直到信号量可用或者超时
		2）不可再中断中等待信号量，但是可以采用 down_trylock 尝试获取信号量
		3）可以在中断中释放信号量
		4）用于互斥时获取和释放必须成对使用（信号量还可以用于同步）
6、 互斥体
	互斥体API：
		//定义并初始化一个互斥体
		DEFINE_MUTEX(name)
		//初始化互斥体
		void mutex_init(mutex *lock)
		//获取互斥体
		void mutex_lock(struct mutex *lock)
		//获取互斥体，但是休眠后能被信号唤醒
		int mutex_lock_interruptible(struct mutex *lock)
		//获取互斥体，但是休眠后能被SIGKILL唤醒
		int mutex_lock_killable(struct mutex *lock)
		//尝试获取互斥体
		int mutex_trylock(struct mutex *lock)
		//释放互斥体
		void mutex_unlock(struct mutex *lock)
		//互斥体是否被获取，如果是的话就返回 1，否则返回 0
		int mutex_is_locked(struct mutex *lock)
	互斥体的特性：
		1）不可再中断中使用，包括 mutex_trylock
		2）不可递归使用，获取和释放必须成对使用
		4）用于互斥时消耗的资源比信号量小，效率更高
